/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package luft27.zorcon;

import java.io.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import luft27.propertytree.PropertyChangedListener;
import luft27.propertytree.PropertyNode;
import luft27.propertytree.PropertyTree;
import luft27.propertytree.PropertyValue;
import luft27.zorcon.ui.MainFrame;
import org.w3c.dom.*;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

/**
 *
 * @author amalikov
 */
public class ZorCon {

	/**
	 * @param args the command line arguments
	 */
	public static void main(String[] args) {
		readSettings(System.getProperty("user.dir") + "/data/config/zorcon.xml");
		
		PropertyTree.INSTANCE.getNode("/settings").addListener(new PropertyChangedListener(){
			@Override
			public void actionPerformed(PropertyValue value) {
				writeSettings(System.getProperty("user.dir") + "/data/config/zorcon.xml");
			}
		});
		
		java.awt.EventQueue.invokeLater(new Runnable() {
			@Override
			public void run() {
				new MainFrame().setVisible(true);
			}
		});
	}

	
	private static void readSettings(String xmlName) {
		try (Reader file = new FileReader(xmlName)) {
            DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
            DocumentBuilder db = dbf.newDocumentBuilder();
            Document doc = db.parse(new InputSource(file));
			recursiveRead(PropertyTree.INSTANCE.getNode("/settings"), doc.getDocumentElement());
        } catch (FileNotFoundException ex) {
			// do nothing
		} catch (SAXException | IOException | ParserConfigurationException ex) {
            Logger.getLogger(ZorCon.class.getName()).log(Level.SEVERE, null, ex);
        }		
	}
	
	private static void writeSettings(String xmlName) {
		try (Writer file = new OutputStreamWriter(new FileOutputStream(xmlName, false), "UTF-8")) {
			StreamResult streamResult = new StreamResult(file);
			TransformerFactory tf = TransformerFactory.newInstance();
			tf.setAttribute("indent-number", 4); 
			Transformer serializer = tf.newTransformer();
			serializer.setOutputProperty(OutputKeys.METHOD, "xml");
			serializer.setOutputProperty(OutputKeys.ENCODING, "UTF-8");
			serializer.setOutputProperty(OutputKeys.INDENT, "yes");

			DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
			DocumentBuilder db = dbf.newDocumentBuilder();
			DOMImplementation impl = db.getDOMImplementation();
			Document doc = impl.createDocument(null, "settings", null);
			doc.setXmlStandalone(true);
			recursiveWrite(PropertyTree.INSTANCE.getNode("/settings"), doc.getDocumentElement(), doc);
			
			serializer.transform(new DOMSource(doc), streamResult);
        } catch (TransformerException | IOException | ParserConfigurationException ex) {
			Logger.getLogger(ZorCon.class.getName()).log(Level.SEVERE, null, ex);
        }
	}
	
	private static void recursiveRead(PropertyNode prop, Node dom) {
		NodeList children = dom.getChildNodes();
		for (int i = 0; i < children.getLength(); ++i) {
			Node domChild = children.item(i);
			if ("node".equals(domChild.getNodeName())) {
				Node domChildName = domChild.getAttributes().getNamedItem("name");
				Node domChildValue = domChild.getAttributes().getNamedItem("value");
				String childValueStr = (domChildValue != null) ? domChildValue.getNodeValue() : "";
			
				if (domChildName != null) {
					PropertyNode propChild = prop.getNode("/" + domChildName.getNodeValue());
					propChild.set(new PropertyValue(childValueStr));
					recursiveRead(propChild, domChild);
				}
			}
		}
	}

	private static void recursiveWrite(PropertyNode prop, Element dom, Document doc) {
		PropertyNode[] propChildren = prop.getChildren();
		for (PropertyNode propChild : propChildren) {
			Element domChild = doc.createElementNS(null, "node");
			domChild.setAttribute("name", propChild.getName());
			domChild.setAttribute("value", propChild.get().asString());
			dom.appendChild(domChild);
			recursiveWrite(propChild, domChild, doc);
		}
	}
}
